package communication.majiang
{
	import com.netease.protobuf.UInt64;
	
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import flash.utils.clearTimeout;
	import flash.utils.getTimer;
	import flash.utils.setTimeout;
	
	import communication.CertManager;
	
	import modules.GameDispatcher;
	import modules.GameEvent;
	import modules.entity.ActionType;
	import modules.majiang.MajiangEvent;
	import modules.majiang.data.CountDownState;
	import modules.majiang.data.MatchCurrentAction;
	import modules.majiang.data.MatchState;
	import modules.majiang.data.TableDataModel;
	import modules.majiang.data.TablePlayerDataModel;
	import modules.majiang.data.TablesDataManager;
	import modules.manager.SoundManager;
	
	import protobuf.BET_POOL;
	import protobuf.DISCARD_INFO;
	import protobuf.E_BET_POOL_CAUSE;
	import protobuf.MSPKG_AUTOHIDE_HANDTILES_ACK;
	import protobuf.MSPKG_BALANCE_NTF;
	import protobuf.MSPKG_BANKER_CHAIR_ID_NTF;
	import protobuf.MSPKG_BET_ACK;
	import protobuf.MSPKG_BET_NTF;
	import protobuf.MSPKG_BET_POOL_NTF;
	import protobuf.MSPKG_BET_ZERO_NTF;
	import protobuf.MSPKG_CALL_NTF;
	import protobuf.MSPKG_CANCHAT_NTF;
	import protobuf.MSPKG_CHANGE_BANKER_CHAIR_ID_NTF;
	import protobuf.MSPKG_CHAT_NTF;
	import protobuf.MSPKG_DICE_NTF;
	import protobuf.MSPKG_DISCARD_ACK;
	import protobuf.MSPKG_DISCARD_NTF;
	import protobuf.MSPKG_DIST_TILES_NTF;
	import protobuf.MSPKG_ENTER_TABLE_ACK;
	import protobuf.MSPKG_FETCH_TILE_NTF;
	import protobuf.MSPKG_FOLD_NTF;
	import protobuf.MSPKG_HELLO_WORLD_ACK;
	import protobuf.MSPKG_INIT_TILES_NTF;
	import protobuf.MSPKG_KICK_PLAYER_NTF;
	import protobuf.MSPKG_LEAVE_SEAT_NTF;
	import protobuf.MSPKG_LEAVE_TABLE_ACK;
	import protobuf.MSPKG_LOSE_TILES_INFO;
	import protobuf.MSPKG_MATCH_FINISH_NTF;
	import protobuf.MSPKG_MATCH_ID_NTF;
	import protobuf.MSPKG_MATCH_START_COOLDOWN_NTF;
	import protobuf.MSPKG_MATCH_START_COOLDOWN_STOP_NTF;
	import protobuf.MSPKG_MONEY_NTF;
	import protobuf.MSPKG_NEED_BET_NTF;
	import protobuf.MSPKG_NEED_CALL_NTF;
	import protobuf.MSPKG_NEED_DISCARD_NTF;
	import protobuf.MSPKG_NOT_ENOUGH_MONEY_NTF;
	import protobuf.MSPKG_PASS_ACK;
	import protobuf.MSPKG_PASS_NTF;
	import protobuf.MSPKG_QUERY_FIRST_CALL_NTF;
	import protobuf.MSPKG_QUERY_SHOWTILES_NTF;
	import protobuf.MSPKG_RAISE_ACK;
	import protobuf.MSPKG_RAISE_NTF;
	import protobuf.MSPKG_SHOW_TILES_NTF;
	import protobuf.MSPKG_SITOUT_NTF;
	import protobuf.MSPKG_SIT_DOWN_ACK;
	import protobuf.MSPKG_SPLICE_TABLE_NTF;
	import protobuf.MSPKG_STANDUP_ACK;
	import protobuf.MSPKG_TABLE_LIVE_INFO_NTF;
	import protobuf.MSPKG_TAKE_SEAT_NTF;
	import protobuf.MSPKG_TILES_NTF;
	import protobuf.MSPKG_TNMT_FINISHED_RPT;
	import protobuf.MSPKG_TNMT_OUTMATCH_RPT;
	import protobuf.MSPKG_TOPUP_ACK;
	import protobuf.MSPKG_TOPUP_NTF;
	import protobuf.MSPKG_TOURNAMENT_REBUY_NTF;
	import protobuf.MSPKG_TOURNAMENT_REST_NTF;
	import protobuf.MSPKG_UPDATE_BLIND_ACK;
	import protobuf.MSPKG_UPDATE_TABLE_BLIND_NTF;
	import protobuf.MSPKG_VPP_NTF;
	import protobuf.MSPKG_WIN_TILES_INFO;
	import protobuf.PKG_AUTH_ACK;
	import protobuf.PKG_AUTH_CHALLENGE_CMD;
	
	import utils.FloatHandler;
	import utils.ResourceManager;
	import utils.TileTransform;

	/**
	 * 处理麻将服务器的协议
	 * @author xumin.xu
	 *
	 */
	public final class MajiangMsgProcessor
	{
		private static var _instance:MajiangMsgProcessor;

		public static function getInstance():MajiangMsgProcessor
		{
			if (_instance == null)
			{
				_instance = new MajiangMsgProcessor();
			}
			return _instance;
		}

		/**
		 * 麻将数据发送者
		 */
		private function get majiangMsgSender():MajiangMsgSender
		{
			return MajiangMsgSender.instance;
		}

		private function get dispatcher():GameDispatcher
		{
			return GameDispatcher.instance;
		}

		public function get certManager():CertManager
		{
			return CertManager.getInstance();
		}

		//每个GameUI对应的 ChatManager
//		public static var chatManagerDic:Dictionary = new Dictionary();

		/**
		 * 处理
		 * @param pkg
		 * 客户端连接其他游戏服务器(目录服务器，游戏逻辑服务器)时，
		 * 将保存的CLIENT_SESSION_CERT发送到服务端，
		 * 服务端用Login服务器的公钥对其签名进行验证，
		 * 服务器向客户端发送随机挑战码，客户端用其会话私钥对挑战码签名，
		 * 将签名结果发回服务端，服务端用客户端用其会话公钥验证挑战码签名，如果通过则客户端通过身份验证。
		 */
		public function OnRecvAuthChallengeCmd(pkg:PKG_AUTH_CHALLENGE_CMD):void
		{
			logger("接收到游戏服挑战码");

			majiangMsgSender.sendChallenge(pkg.challengeCode);

		}

		public function OnRecvAuthAck(pkg:PKG_AUTH_ACK):void
		{
			logger("游戏服挑战码验证结果");

			majiangMsgSender.handleAuthResult(pkg);
		}

		public function OnRecvHelloWorldAck(pkg:MSPKG_HELLO_WORLD_ACK):void
		{

		}

		public function OnRecvEnterTableAck(pkg:MSPKG_ENTER_TABLE_ACK):void
		{
			logger("服务器响应进入桌子");

			switch (pkg.errorCode)
			{
				case 0:
					dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_ENTER_TABLE_ACK.toString(), pkg));
					dispatcher.dispatchEvent(new GameEvent(GameEvent.SHOW_WAIT_INFO));
					break;
				default:
					logger("进入桌子失败");
					break;
			}
		}

		/**
		 * 坐下
		 * @param pkg
		 */
		public function OnRecvSitDownAck(pkg:MSPKG_SIT_DOWN_ACK):void
		{
			//桌子编号
			switch (pkg.errorCode)
			{
				case 0:
					logger("玩家坐下请求成功");
					var sitDownAck:MSPKG_SIT_DOWN_ACK = pkg;
					var tableId:UInt64 = sitDownAck.tableId;
					var chairId:uint = sitDownAck.chairId;

					var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

					//标记玩家自己坐下
					tableDataModel.sitChairId = chairId;
					//观看游戏位置
					tableDataModel.lookChairId = chairId;
					tableDataModel.money = 0;

					//刷新界面
					dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.UPDATE_MAJIANG_TABLE_VIEW, {tableId:tableId}));
					break;
				case 1:
					logger("坐下请求处理失败,位置不对");
					break;
				case 2:
					logger("坐下请求处理失败,座位上有人");
					var showInfo:String = ResourceManager.getInstance().getString('MahjongResource', 'sitDown_fail');
					dispatcher.dispatchEvent(new GameEvent(GameEvent.SHOW_WARN_INFO, showInfo));
					break;
				case 3:
					logger("坐下请求处理失败,已经坐下");
					break;
				case 4:
					logger("坐下请求处理失败,已经订了座位");
					break;
				case 5:
					logger("坐下请求处理失败,已经订了座位");
					break;
				case 6:
					logger("坐下请求处理失败,钱不对");
					break;
				case 7:
					logger("坐下请求处理失败,座子已经关闭");
					break;
				case 8:
					logger("坐下请求处理失败,数据库返回钱不够");
					break;
				case 9:
					logger("坐下请求处理失败,vpp值不够");
					break;
				case 10:
					logger("坐下请求处理失败,数据库显示运营商不匹配");
					break;
				case 11:
					logger("坐下请求处理失败,数据库显示无法取得正确的汇率");
					break;
				default:
					logger("坐下请求处理失败,错误码为" + pkg.errorCode);
					break;
			}
		}

		/**
		 * 服务器通知客户端需要充值
		 * @param pkg
		 *
		 */
		public function OnRecvTopupNtf(pkg:MSPKG_TOPUP_NTF):void
		{
			dispatcher.dispatchEvent(new MajiangMsgEvent(MajiangEvent.SHOW_CASHIER_VIEW, pkg));
		}

		/**
		 *服务器的充值请求成功与否的答复
		 */
		public function OnRecvTopupAck(pkg:MSPKG_TOPUP_ACK):void
		{
			switch (pkg.errorCode)
			{
				case 0:
					logger("服务器的充值成功");
					break;
				default:
					logger("服务器的充值失败,错误码：" + pkg.errorCode);
					break;
			}
		}

		/**
		 * 玩家本桌钱数的变化通知
		 * @param pkg
		 */
		public function OnRecvMoneyNtf(pkg:MSPKG_MONEY_NTF):void
		{
			logger("玩家本桌钱数的变化通知");
			var startTime:int = getTimer();

			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;
			var money:Number = pkg.money;
			//变化值
			pkg.delta;

			logger("座位编号为 " + chairId + " 的玩家本桌钱更新为 " + money);

			//更新玩家本游戏内赌注
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			if (chairId == tableDataModel.sitChairId)
			{
				tableDataModel.money = money;
			}

			var tablePlayerDataModel:TablePlayerDataModel = tableDataModel.seatedPlayers[chairId];
			if (tablePlayerDataModel != null)
			{
				tablePlayerDataModel.money = money;

				/*if (pkg.hasCause && pkg.cause == E_MONEY_CAUSE.E_MONEY_CAUSE_WIN)
				{
					var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
					chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: MessageType.GET, money: pkg.delta});
				}*/
			}
			logger("玩家本桌钱数的变化通知处理时长：" + (getTimer() - startTime));
		}

		/**
		 * 响应离开客户端桌子请求
		 */
		public function OnRecvLeaveTableAck(pkg:MSPKG_LEAVE_TABLE_ACK):void
		{
			switch (pkg.errorCode)
			{
				case 0:
					logger("离开桌子成功");

					//关闭打开的购买赌注界面
					dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.CLOSE_CASHIER_VIEW));

					dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_LEAVE_TABLE_ACK.toString(), {tableIdStr: pkg.tableId.toString()}));
					break;
				default:
					logger("离开桌子失败");

					break;
			}
		}

		/**
		 * 响应离开客户端站起请求
		 */
		public function OnRecvStandupAck(pkg:MSPKG_STANDUP_ACK):void
		{
			logger("响应离开客户端站起请求");
			switch (pkg.errorCode)
			{
				case 0:
					logger("玩家自己站起成功");
					//将这个所在桌子的下注金额重置
					if (TablesDataManager.tableDataModeDic[pkg.tableId.toString()])
					{
						TablesDataManager.tableDataModeDic[pkg.tableId.toString()].money = 0;
					}
					//关闭打开的购买赌注界面
					dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.CLOSE_CASHIER_VIEW));
					break;
				default:
					logger("站起请求处理失败,错误码为" + pkg.errorCode);
					break;
			}
		}

		/**
		 * 通知有玩家加入了本桌的某个位置上
		 * @param pkg
		 */
		public function OnRecvTakeSeatNtf(pkg:MSPKG_TAKE_SEAT_NTF):void
		{
			var takeSeatNtf:MSPKG_TAKE_SEAT_NTF = pkg;
			var tableId:UInt64 = takeSeatNtf.tableId;
			var chairId:uint = takeSeatNtf.chairId;

			var money:Number = takeSeatNtf.money;

			var playerName:String = certManager.convertByteArrayToString(takeSeatNtf.playerName);

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			logger("通知有玩家加入了桌子名为" + tableId.toString() + "的" + chairId + "号位置上 ");

			//在座位上添加玩家自己
			var tablePlayerDataModel:TablePlayerDataModel = new TablePlayerDataModel();

			tablePlayerDataModel.chairId = chairId;
			tablePlayerDataModel.userName = playerName;
			tablePlayerDataModel.money = money;

			if (chairId == tableDataModel.sitChairId)
			{
				tablePlayerDataModel.money = tableDataModel.money;
			}

			tablePlayerDataModel.avatarId = takeSeatNtf.avatarId;

			tableDataModel.seatedPlayers[chairId] = tablePlayerDataModel;

			tableDataModel.playerTiles[chairId].length = 0;

			//刷新界面
			dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.UPDATE_MAJIANG_TABLE_VIEW, {tableId:tableId}));

		}

		/**
		 * 通知玩家离开座位
		 * @param pkg
		 */
		public function OnRecvLeaveSeatNtf(pkg:MSPKG_LEAVE_SEAT_NTF):void
		{
			logger("通知玩家离开座位");
			var startTime:int = getTimer();

			var leaveSeatNtf:MSPKG_LEAVE_SEAT_NTF = pkg;
			var tableId:UInt64 = leaveSeatNtf.tableId;
			var chairId:uint = leaveSeatNtf.chairId;

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			//把自己座位上的数据清空
			tableDataModel.seatedPlayers[chairId] = null;

			tableDataModel.playerTiles[chairId] = [];

			//把玩家从离开的玩家列表中删除
			for (var i:int = 0; i < tableDataModel.sitOutPlayerList.length; i++)
			{
				if (tableDataModel.sitOutPlayerList[i].chairId == chairId)
				{
					tableDataModel.sitOutPlayerList.splice(i, 1);
					break;
				}
			}

			//判断是否为自己离开座位
			if (tableDataModel.sitChairId == chairId)
			{
				//清空手牌
				tableDataModel.tilesInHand = [];

				tableDataModel.sitChairId = -1;
				//观看游戏位置
				tableDataModel.lookChairId = 1;

				tableDataModel.gameUIState.isAutoBuyin = false;

				tableDataModel.gameUIState.isSitOut = false;


				//关闭打开的购买赌注界面
				dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.CLOSE_CASHIER_VIEW));
			}

			//刷新庄家图标的显示
			tableDataModel.updateOwnDealerVisble();

			//刷新界面
			dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.UPDATE_MAJIANG_TABLE_VIEW, {tableId:tableId}));

			logger("通知玩家离开座位处理时长：" + (getTimer() - startTime));
		}

		/**
		 *比赛开始前的倒计时
		 * @param pkg
		 */
		public function OnRecvMatchStartCoolDownNtf(pkg:MSPKG_MATCH_START_COOLDOWN_NTF):void
		{
			logger("比赛开始前的倒计时 ");
			var startTime:int = getTimer();

			var tableId:UInt64 = pkg.tableId;

			//比赛开始前的倒计时
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			//3秒摇色子时间
			var cooldown:uint = pkg.cooldown;
			if (tableDataModel.recvDiceNtf != null)
			{
				cooldown -= 3;
			}
			cooldown = cooldown > 9 ? 9 : cooldown;
			cooldown = cooldown < 1 ? 1 : cooldown;


			//修改比赛状态 为 开始倒计时
			tableDataModel.setMatchState(MatchState.COUNTDOWN);

			tableDataModel.matchStartCountDown = cooldown;
			tableDataModel.matchStartCountDownVisible = true;

			if (tableDataModel.countDownTimer)
			{
				tableDataModel.countDownTimer.stop();
			}
			tableDataModel.countDownTimer = new Timer(1000, tableDataModel.matchStartCountDown);
			tableDataModel.countDownTimer.addEventListener(TimerEvent.TIMER, function(event:Event):void
			{
				tableDataModel.matchStartCountDown--;
			});
			tableDataModel.countDownTimer.addEventListener(TimerEvent.TIMER_COMPLETE, function(event:Event):void
			{
				tableDataModel.matchStartCountDownVisible = false;
				//倒计时结束 开始摇色子
				if (tableDataModel.recvDiceNtf != null)
				{
					SoundManager.instance.numTimerSoundPlay(false, tableId);
					dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.WAVE_PARTICLE_START, tableDataModel.recvDiceNtf));
				}
				else
				{
					logger("倒计时后没有给色子的值，或者接受到 停止比赛开始前的倒计时 的协议");
				}
				tableDataModel.recvDiceNtf = null;
			});
			tableDataModel.countDownTimer.start();
			SoundManager.instance.numTimerSoundPlay(true, tableId);

			logger("比赛开始前的倒计时处理时长：" + (getTimer() - startTime));
		}

		/**
		 * 掷骰子庄家座位ID
		 * @param pkg
		 */
		public function OnRecvDiceNtf(pkg:MSPKG_DICE_NTF):void
		{
			logger("掷骰子,结果为" + pkg.dice + "点");

			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			//等待 倒计时完成使用
			tableDataModel.recvDiceNtf = pkg;
		}

		/**
		 * 停止比赛开始前的倒计时
		 * @param pkg
		 */
		public function OnRecvMatchStartCoolDownStopNtf(pkg:MSPKG_MATCH_START_COOLDOWN_STOP_NTF):void
		{
			logger("停止比赛开始前的倒计时 ");

			var tableId:UInt64 = pkg.tableId;
			//比赛开始前的倒计时
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			tableDataModel.recvDiceNtf = null;
			if (tableDataModel.countDownTimer)
			{
				tableDataModel.countDownTimer.stop();
			}
			SoundManager.instance.numTimerSoundPlay(false, tableId);

			//不显示游戏倒计时
			tableDataModel.matchStartCountDownVisible = false;

			//修改比赛状态 
			tableDataModel.setMatchState(MatchState.WAIT);
		}

		/**
		 * 广播庄家的桌位ID
		 **/
		public function OnRecvBankerChairIDNtf(pkg:MSPKG_BANKER_CHAIR_ID_NTF):void
		{
			logger("广播庄家的桌位ID" + pkg.bankerChairId);

			var tableId:UInt64 = pkg.tableId;

			//比赛开始前的倒计时
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			tableDataModel.bankerId = pkg.bankerChairId;
		}

		/**
		 *第一轮的7张牌
		 * @param pkg
		 */
		public function OnRecvInitTilesNtf(pkg:MSPKG_INIT_TILES_NTF):void
		{
			logger("第一轮的7张牌");

			var tableId:UInt64 = pkg.tableId;
			var tiles:Array = TileTransform.arrServerToClient(pkg.tiles);
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			tableDataModel.playerTiles[tableDataModel.sitChairId] = tiles.concat();

			tableDataModel.tilesInHand = tiles;

			//给牌排序
			tableDataModel.tilesInHand.sort(TileTransform.sortOnClientTile);

			//清空桌面上的牌
			tableDataModel.tilesOnTable = [];

			//刷新界面显示
			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_INIT_TILES_NTF.toString(), pkg));

		}

		/**
		 *从牌堆中发一张牌
		 * @param pkg
		 */
		public function OnRecvFetchTileNtf(pkg:MSPKG_FETCH_TILE_NTF):void
		{
			logger("从牌堆中发一张牌");
			var startTime:int = getTimer();

			//执行发牌动作 自己得到一张为 pkg.tile 的牌
			var tableId:UInt64 = pkg.tableId;
			var tile:Object = TileTransform.serverToClient(pkg.tile);

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			tableDataModel.tilesInHand[tableDataModel.handTilesNum] = tile;

			tableDataModel.playerTiles[tableDataModel.sitChairId][tableDataModel.handTilesNum] = tile;

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_FETCH_TILE_NTF.toString(), pkg));
			logger("从牌堆中发一张牌处理时长：" + (getTimer() - startTime));
		}

		/**
		 * 广播给玩家发牌
		 **/
		public function OnRecvDistTilesNtf(pkg:MSPKG_DIST_TILES_NTF):void
		{
			logger("广播给玩家发牌");
			var startTime:int = getTimer();
			var tableId:UInt64 = pkg.tableId;

			//发牌椅子列表
			var chairList:Array = pkg.chairId;
			//发牌数量
			var tilesCount:int = pkg.tilesCount;
			//剩余牌数
			var tilesWallCount:int = pkg.tilesWallCount;

			var currentTime:int = getTimer();

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			//桌面上剩余牌数
			tableDataModel.restCardData.restMajiangNum = tilesWallCount;

			var chairId:int;
			var tiles:Array;
			if (tilesCount == TableDataModel.GAME_TYPE_TILE_SEVEN)
			{
				//设置游戏状态
				tableDataModel.setMatchState(MatchState.INGAME);
				tableDataModel.handTilesNum = TableDataModel.GAME_TYPE_TILE_SEVEN;

				for each (chairId in chairList)
				{
					tiles = tableDataModel.playerTiles[chairId];
					tiles.length = TableDataModel.GAME_TYPE_TILE_SEVEN;
					//确定参与本比赛的玩家列表
					tableDataModel.inMatchPlayerList.push({timer: currentTime, chairId: chairId});
				}
			}
			else if (tilesCount == TableDataModel.GAME_TYPE_TILE_FOUR)
			{
				//设置游戏状态
				tableDataModel.setMatchState(MatchState.INGAME);
				tableDataModel.handTilesNum = TableDataModel.GAME_TYPE_TILE_FOUR;

				for each (chairId in chairList)
				{
					tiles = tableDataModel.playerTiles[chairId];
					tiles.length = TableDataModel.GAME_TYPE_TILE_FOUR;
					//确定参与本比赛的玩家列表
					tableDataModel.inMatchPlayerList.push({timer: currentTime, chairId: chairId});
				}
			}
			//发一张牌时出现动画
			else if (tilesCount == 1)
			{
				//发牌特效
				tableDataModel.fetchEffectData.fetchCard(chairList);
			}

			var betPlayers:Array = [];
			//把上轮的押注计算到奖池中
			for (var actionChairId:String in tableDataModel.epicycleBetInfos)
			{
				if (tableDataModel.epicycleBetInfos[actionChairId] != null && tableDataModel.epicycleBetInfos[actionChairId].totalBet > 0)
				{
					tableDataModel.totalBetInGame[int(actionChairId) - 1] = tableDataModel.epicycleBetInfos[actionChairId].totalBet;
					if (tableDataModel.epicycleBetInfos[actionChairId].currentBet > 0)
					{
						betPlayers.push(int(actionChairId));
					}
				}
			}
			tableDataModel.epicycleBetInfos = [];

			//播放 赌注飞往奖池 动画
			if (betPlayers.length > 0)
			{
				tableDataModel.chipsToPotEffectData.chipsToPot(betPlayers);
			}

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_DIST_TILES_NTF.toString(), pkg));
			logger("广播给玩家发牌处理时长：" + (getTimer() - startTime));
		}

		/**
		 *第一轮的要求押注请求
		 * @param pkg
		 */
		public function OnRecvQueryFirstCallNtf(pkg:MSPKG_QUERY_FIRST_CALL_NTF):void
		{
			logger("第一轮的要求押注请求," + pkg.chairId);
			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			//游戏当前动作
			var matchCurrentAction:MatchCurrentAction = tableDataModel.matchCurrentAction;
			matchCurrentAction.currentAction = ActionType.CALL;
			matchCurrentAction.currentChairId = chairId;
			matchCurrentAction.callMoney = pkg.callMoney;

			logger("要求座位编号为 " + chairId + " 的玩家押注  " + pkg.callMoney);

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			tablePlayerDataModel.isCurrentActionPlayer = true;

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.totalTime = tableDataModel.tableDataFromLobby.responseTime * 1000;
			countDownState.startTime = new Date().time;

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_NEED_CALL_NTF.toString(), tableId.toString()));
		}

		/**
		 *要求客户端跟注或加注
		 * @param pkg
		 */
		public function OnRecvNeedCallNtf(pkg:MSPKG_NEED_CALL_NTF):void
		{
			logger("要求客户端跟注或加注" + pkg.chairId);
			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			//游戏当前动作
			var matchCurrentAction:MatchCurrentAction = tableDataModel.matchCurrentAction;
			matchCurrentAction.currentAction = ActionType.CALL;
			matchCurrentAction.currentChairId = chairId;
			matchCurrentAction.callMoney = pkg.callMoney;
			matchCurrentAction.minRaiseMoney = pkg.minRaiseMoney;

			logger("要求座位编号为 " + chairId + " 的玩家押注  " + pkg.callMoney);

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			tablePlayerDataModel.isCurrentActionPlayer = true;

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.totalTime = tableDataModel.tableDataFromLobby.responseTime * 1000;
			countDownState.startTime = new Date().time;

			if (pkg.hasMaxRaiseMoney)
			{
				tableDataModel.maxRaiseMoney = pkg.maxRaiseMoney;
			}
			else
			{
				tableDataModel.maxRaiseMoney = Number.MAX_VALUE;
			}

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_NEED_CALL_NTF.toString(), tableId.toString()));
		}

		/**
		 * 用户弃牌广播
		 **/
		public function OnRecvFoldNtf(pkg:MSPKG_FOLD_NTF):void
		{
			logger("用户弃牌广播,座位号：" + pkg.chairId);
			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;
			var timer:int = getTimer();

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			//添加弃牌玩家列表
			tableDataModel.foldPlayerList.push({timer: timer, chairId: chairId});

			tableDataModel.bonusPotsData.updateView();

			//把玩家从正在比赛的玩家列表中删除
			for (var i:int = 0; i < tableDataModel.inMatchPlayerList.length; i++)
			{
				if (tableDataModel.inMatchPlayerList[i].chairId == chairId)
				{
					tableDataModel.inMatchPlayerList.splice(i, 1);
					break;
				}
			}

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			if (tablePlayerDataModel != null)
			{
				tablePlayerDataModel.isCurrentActionPlayer = false;
			}

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.stopCountDown();


			//添加系统资讯
			/*var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
			chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: MessageType.FOLD});
*/
			if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
			{
				SoundManager.instance.actionSoundPlay("fold");
			}

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_FOLD_NTF.toString(), tableId.toString()));
		}

		/**
		 * 用户跟牌广播
		 **/
		public function OnRecvCallNtf(pkg:MSPKG_CALL_NTF):void
		{
			logger("用户跟牌广播" + pkg.chairId);

			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;
			//这次跟注金额
			var money:Number = pkg.money;
			//本轮总下注金额
			var totalBet:Number = pkg.totalBet;

			logger("广播座位编号为 " + chairId + " 的玩家跟注  " + money);

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			var epicycleAction:Array = tableDataModel.epicycleBetInfos;

			//计算本轮下注金额
			var currentBet:Number = totalBet - tableDataModel.totalBetInGame[chairId - 1];
			epicycleAction[chairId] = {action: ActionType.CALL, value: money, currentBet: currentBet, totalBet: totalBet};

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			tablePlayerDataModel.isCurrentActionPlayer = false;

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.stopCountDown();


			//添加系统资讯
			/*var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
			chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: MessageType.CALL, money: money});
			if (FloatHandler.TwoFormat(tablePlayerDataModel.money) == 0)
			{
				chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: "allInPlayer"});
			}*/

			tableDataModel.matchCurrentAction.clear();

			/*if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
			{
				SoundManager.instance.actionSoundPlay("call");
			}*/
			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_CALL_NTF.toString(), tableId.toString()));
		}

		/**
		 * 用户加注响应
		 **/
		public function OnRecvRaiseAck(pkg:MSPKG_RAISE_ACK):void
		{
			switch (pkg.errorCode)
			{
				case 0:
					logger("用户加注成功");
					break;
				default:
					logger("用户加注失败");
					break;
			}
		}

		/**
		 * 用户加注广播
		 **/
		public function OnRecvRaiseNtf(pkg:MSPKG_RAISE_NTF):void
		{
			logger("用户加注广播" + pkg.chairId);

			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;
			var money:Number = pkg.money;
			//本场总下注金额
			var totalBet:Number = pkg.totalBet;

			logger("广播座位编号为 " + chairId + " 的玩家加注  " + money);

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			var epicycleAction:Array = tableDataModel.epicycleBetInfos;

			//计算本轮下注金额
			var currentBet:Number = currentBet = totalBet - tableDataModel.totalBetInGame[chairId - 1];
			epicycleAction[chairId] = {action: ActionType.RAISE, value: money, totalBet: totalBet, currentBet: currentBet};

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			tablePlayerDataModel.isCurrentActionPlayer = false;

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.stopCountDown();


			//添加系统资讯
			/*var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
			chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: MessageType.RAISE, money: money});
			if (FloatHandler.TwoFormat(tablePlayerDataModel.money) == 0)
			{
				chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: "allInPlayer"});
			}*/

			tableDataModel.matchCurrentAction.clear();

			/*if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
			{
				SoundManager.instance.actionSoundPlay("raise");
			}*/

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_RAISE_NTF.toString(), tableId.toString()));
		}

		/**
		 *要求客户端下注、过牌
		 * @param pkg
		 */
		public function OnRecvNeedBetNtf(pkg:MSPKG_NEED_BET_NTF):void
		{
			logger("要求客户端下注、过牌" + pkg.chairId);

			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;
			var minBetMoney:Number = pkg.minBetMoney;

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			//游戏当前动作
			var matchCurrentAction:MatchCurrentAction = tableDataModel.matchCurrentAction;
			matchCurrentAction.currentAction = ActionType.BET;
			matchCurrentAction.currentChairId = chairId;
			matchCurrentAction.minRaiseMoney = pkg.minBetMoney;

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			tablePlayerDataModel.isCurrentActionPlayer = true;

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.totalTime = tableDataModel.tableDataFromLobby.responseTime * 1000;
			countDownState.startTime = new Date().time;

			if (pkg.hasMaxBetMoney)
			{
				tableDataModel.maxRaiseMoney = pkg.maxBetMoney;
			}
			else
			{
				tableDataModel.maxRaiseMoney = Number.MAX_VALUE;
			}

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_NEED_BET_NTF.toString(), tableId.toString()));
		}

		/**
		 * 用户过牌响应
		 **/
		public function OnRecvPassAck(pkg:MSPKG_PASS_ACK):void
		{
			switch (pkg.errorCode)
			{
				case 0:
					logger("过牌成功");
					break;
				default:
					logger("过牌失败");
					break;
			}
		}

		/**
		 * 用户过牌广播
		 **/
		public function OnRecvPassNtf(pkg:MSPKG_PASS_NTF):void
		{
			logger("用户过牌广播" + pkg.chairId);

			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;
			//本场总下注金额
			var totalBet:Number = 0;
			//计算本轮下注金额
			var currentBet:Number = 0;

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			if(tableDataModel == null) return;
			totalBet = tableDataModel.totalBetInGame[chairId - 1];

			var epicycleAction:Array = tableDataModel.epicycleBetInfos;
			if (epicycleAction[chairId] != null)
			{
				totalBet = epicycleAction[chairId].totalBet;
				currentBet = epicycleAction[chairId].currentBet;
			}
			epicycleAction[chairId] = {action: ActionType.CHECK, totalBet: totalBet, currentBet: currentBet};

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			tablePlayerDataModel.isCurrentActionPlayer = false;

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.stopCountDown();


			//添加系统资讯
			/*var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
			chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: MessageType.CHECK});

			tableDataModel.matchCurrentAction.clear();

			if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
			{
				SoundManager.instance.actionSoundPlay("check");
			}*/

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_PASS_NTF.toString(), tableId.toString()));
		}

		/**
		 * 用户押注响应
		 */
		public function OnRecvBetAck(pkg:MSPKG_BET_ACK):void
		{
			logger("用户押注响应");
			switch (pkg.errorCode)
			{
				case 0:
					logger("过牌成功");
					break;
				default:
					logger("过牌失败");
					break;
			}
		}

		/**
		 * 用户押注广播
		 */
		public function OnRecvBetNtf(pkg:MSPKG_BET_NTF):void
		{
			logger("用户押注广播" + pkg.chairId);

			var tableId:UInt64 = pkg.tableId;
			var chairId:uint = pkg.chairId;
			var money:Number = pkg.money;
			//本轮总下注金额
			var totalBet:Number = pkg.totalBet;

			logger("广播座位编号为 " + chairId + " 的玩家押注  " + money);

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			var epicycleAction:Array = tableDataModel.epicycleBetInfos;

			//计算本轮下注金额
			var currentBet:Number = totalBet - tableDataModel.totalBetInGame[chairId - 1];
			epicycleAction[chairId] = {action: ActionType.BET, value: money, totalBet: totalBet, currentBet: currentBet};

			//更新玩家当前是否能操作
			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
			tablePlayerDataModel.isCurrentActionPlayer = false;

			//更新倒计时数据
			var countDownStates:Array = tableDataModel.countDownStates;
			var countDownState:CountDownState = countDownStates[chairId];
			countDownState.stopCountDown();


			//添加系统资讯
			/*var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
			chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: MessageType.BET, money: money});
			if (FloatHandler.TwoFormat(tablePlayerDataModel.money) == 0)
			{
				chatManager.addLogger(tableDataModel, {name: tablePlayerDataModel.userName, type: "allInPlayer"});
			}*/

			tableDataModel.matchCurrentAction.clear();

			/*if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
			{
				SoundManager.instance.actionSoundPlay("bet");
			}*/

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_BET_NTF.toString(), tableId.toString()));
		}

		/**
		 *要求客户端出牌
		 * @param pkg
		 */
		public function OnRecvNeedDiscardNtf(pkg:MSPKG_NEED_DISCARD_NTF):void
		{
			logger("要求客户端出牌 ");

			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var countDownStates:Array = tableDataModel.countDownStates;
			for (var i:int = 1; i <= 6; i++)
			{
				if (seatedPlayers[i] != null && tableDataModel.isInMatch(i))
				{
					//更新玩家当前是否能操作
					var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[i];
					tablePlayerDataModel.isCurrentActionPlayer = true;

					//更新倒计时数据
					var countDownState:CountDownState = countDownStates[i];
					countDownState.totalTime = tableDataModel.tableDataFromLobby.discardTime * 1000;
					countDownState.startTime = new Date().time;
				}
			}
			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_NEED_DISCARD_NTF.toString(), pkg));
		}

		/**
		 *回应玩家出牌请求
		 * @param pkg
		 *
		 */
		public function OnRecvDiscardAck(pkg:MSPKG_DISCARD_ACK):void
		{
			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			switch (pkg.errorCode)
			{
				case 0:
					tableDataModel.disableDiscard = false;

					var clientTile:Object = TileTransform.serverToClient(pkg.tile);

					//从自己手牌中拿掉该牌
					var tilesInHand:Array = tableDataModel.tilesInHand;

					var length:int = tilesInHand.length;
					var i:int = 0;
					for (; i < length; i++)
					{
						if (tilesInHand[i].type == clientTile.type && tilesInHand[i].value == clientTile.value)
						{
							//删除该牌
							tilesInHand.splice(i, 1);
							tableDataModel.disableDiscard = false;
							break;
						}
					}
					//给牌排序
					tilesInHand.sort(TileTransform.sortOnClientTile);

					//播放显示自己出得牌动画
					tableDataModel.discardCardEffectData.showOwnDiscard(clientTile);

					/*if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
					{
						SoundManager.instance.tileSoundPlay(clientTile.type, clientTile.value);
					}*/

					dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_DISCARD_ACK.toString(), tableId.toString()));

					logger("回应玩家出牌请求 成功");
					break;
				default:
					logger("回应玩家出牌请求 失败");
					break;
			}

		}

		/**
		 * 其他玩家出牌的广播
		 * @param pkg
		 */
		public function OnRecvDiscardNtf(pkg:MSPKG_DISCARD_NTF):void
		{
			logger("其他玩家出牌的广播 ");
			var startTime:int = getTimer();
			var tableId:UInt64 = pkg.tableId;

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			
			if(tableDataModel == null) return;
			
			tableDataModel.disableDiscard = false;

			var seatedPlayers:Array = tableDataModel.seatedPlayers;

			//自己出牌的位置
			var ownCardIndex:int = -1;

			var discards:Array = [];
			for each (var info:DISCARD_INFO in pkg.info)
			{
				var chairId:int = info.chairId;
				//转换为客户端牌表现形式
				var clientTile:Object = TileTransform.serverToClient(info.tile);
				//在桌子上添加该牌
				tableDataModel.tilesOnTable.push(clientTile);
				discards.push({chairId: chairId, type: clientTile.type, value: clientTile.value, onTableIndex: tableDataModel.tilesOnTable.length - 1});

				//更新玩家当前是否能操作
				var tablePlayerDataModel:TablePlayerDataModel = seatedPlayers[chairId];
				tablePlayerDataModel.isCurrentActionPlayer = false;

				if (tablePlayerDataModel != null)
				{
					//标记玩家手上有7张牌
					tableDataModel.playerTiles[chairId].length = tableDataModel.handTilesNum;
				}

				//更新倒计时数据
				var countDownStates:Array = tableDataModel.countDownStates;
				var countDownState:CountDownState = countDownStates[chairId];
				countDownState.stopCountDown();

				//从自己手牌中拿掉该牌
				var tilesInHand:Array = tableDataModel.tilesInHand;

				//如果出牌玩家是自己
				if (tableDataModel.sitChairId == chairId && tilesInHand.length == (tableDataModel.handTilesNum + 1))
				{

					var length:int = tilesInHand.length;
					for (var i:int = 0; i < length; i++)
					{
						if (tilesInHand[i].type == clientTile.type && tilesInHand[i].value == clientTile.value)
						{
							ownCardIndex = i;
							//删除该牌
							tilesInHand.splice(i, 1);
							tableDataModel.disableDiscard = false;
							break;
						}
					}
					//给牌排序
					tilesInHand.sort(TileTransform.sortOnClientTile);

					/*if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
					{
						SoundManager.instance.tileSoundPlay(clientTile.type, clientTile.value);
					}*/
				}
			}

			//玩家出牌动画
			tableDataModel.discardCardEffectData.discardCard(discards, ownCardIndex);

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_DISCARD_NTF.toString(), pkg));
			logger("其他玩家出牌的广播处理时长：" + (getTimer() - startTime));
		}

		/**
		 * 赢牌输牌的时候show自己的牌
		 * @param pkg
		 */
		public function OnRecvShowTilesNtf(pkg:MSPKG_SHOW_TILES_NTF):void
		{
			logger("赢牌的时候show自己的牌 ");
			var startTime:int = getTimer();

			var tableId:UInt64 = pkg.tableId;
			var winInfos:Array = pkg.winInfos;
			var loseInfos:Array = pkg.loseInfos;
			//是否是流局，内容在win_finso里面
			var isDraw:Boolean = pkg.isDraw;

			var timer:int = getTimer();

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			var seatedPlayers:Array = tableDataModel.seatedPlayers;
			var countDownStates:Array = tableDataModel.countDownStates;
			var tablePlayerDataModel:TablePlayerDataModel;
			var countDownState:CountDownState;

			var i:int = 0;

			//赢牌玩家列表
			var winChairIds:Array = [];
			//添加赢牌玩家信息
			for each (var winInfo:MSPKG_WIN_TILES_INFO in winInfos)
			{
				//更新玩家当前是否能操作
				tablePlayerDataModel = seatedPlayers[winInfo.chairId];
				if (tablePlayerDataModel)
				{
					tablePlayerDataModel.isCurrentActionPlayer = false;
					//设置赢牌信息
					if (winInfo.tiles.length > 0)
					{
						tableDataModel.playerTiles[winInfo.chairId] = TileTransform.arrServerToClient(winInfo.tiles.sort(TileTransform.sortOnServerTile));
					}
					if (isDraw)
					{
						//把玩家添加到流局列表
						tableDataModel.drawPlayerList.push({timer: timer, chairId: winInfo.chairId});
					}
					else
					{
						//把玩家添加到赢牌列表
						tableDataModel.winPlayerList.push({timer: timer, chairId: winInfo.chairId});
						//判断是否为自己赢牌
						if (tableDataModel.sitChairId == winInfo.chairId)
						{
							/*if (UIAllRefer.instance.getGameUIbyTableId(tableId).visible == true)
							{
								SoundManager.instance.winSoundPlay();
							}*/
						}
					}
				}

				//把玩家从正在比赛的玩家列表中删除
				for (i = 0; i < tableDataModel.inMatchPlayerList.length; i++)
				{
					if (tableDataModel.inMatchPlayerList[i].chairId == winInfo.chairId)
					{
						tableDataModel.inMatchPlayerList.splice(i, 1);
						break;
					}
				}

				winChairIds.push(winInfo.chairId);

				//更新倒计时数据
				countDownState = countDownStates[winInfo.chairId];
				countDownState.stopCountDown();

			}
			//播放赢牌玩家动画
			tableDataModel.chipsFromPotEffectData.fetch(winChairIds);

			//添加输牌玩家信息
			for each (var loseInfo:MSPKG_LOSE_TILES_INFO in loseInfos)
			{
				//更新玩家当前是否能操作
				tablePlayerDataModel = seatedPlayers[loseInfo.chairId];
				if (tablePlayerDataModel)
				{
					tableDataModel.losePlayerList.push({timer: timer, chairId: loseInfo.chairId});
					tablePlayerDataModel.isCurrentActionPlayer = false;

					if (loseInfo.tiles.length > 0)
					{
						tableDataModel.playerTiles[loseInfo.chairId] = TileTransform.arrServerToClient(loseInfo.tiles.sort(TileTransform.sortOnServerTile));
					}
				}

				//更新倒计时数据
				countDownState = countDownStates[loseInfo.chairId];
				countDownState.stopCountDown();

				//把玩家从正在比赛的玩家列表中删除
				for (i = 0; i < tableDataModel.inMatchPlayerList.length; i++)
				{
					if (tableDataModel.inMatchPlayerList[i].chairId == loseInfo.chairId)
					{
						tableDataModel.inMatchPlayerList.splice(i, 1);
						break;
					}
				}

			}

			//清空本轮下注清空，有玩家赢牌时，下注状态已经结束
			tableDataModel.epicycleBetInfos = [];

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_SHOW_TILES_NTF.toString(), pkg));
			logger("赢牌的时候show自己的牌处理时长：" + (getTimer() - startTime));
		}

		/**
		 * 广播比赛结束
		 **/
		public function OnRecvMatchFinishNtf(pkg:MSPKG_MATCH_FINISH_NTF):void
		{
			logger("比赛结束广播");
			var startTime:int = getTimer();

			var tableId:UInt64 = pkg.tableId;

			//比赛开始前的倒计时
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			//设置游戏状态
			tableDataModel.setMatchState(MatchState.WAIT);
			tableDataModel.bonusPotsData.updateView();

			//清空状态
			tableDataModel.disableDiscard = false;

			tableDataModel.matchCurrentAction.clear();
			tableDataModel.epicycleBetInfos = [];

			tableDataModel.totalBetInGame = [0, 0, 0, 0, 0, 0];

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_MATCH_FINISH_NTF.toString()));

			var timeoutId1:uint = setTimeout(function():void
			{
				clearTimeout(timeoutId1);
				//延时1s，处理买入问题 （等待金钱变化完成）

				//处理自动买入
				if (tableDataModel.gameUIState.isAutoBuyin == true && tableDataModel.money < tableDataModel.gameUIState.autoBuyinMoney && tableDataModel.sitChairId > 0)
				{
					var buyinMoney:Number = tableDataModel.gameUIState.autoBuyinMoney - tableDataModel.money;
					dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_TOPUP_REQ.toString(), {tableId: tableId, money: buyinMoney}));

					//添加系统资讯
//					var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
//					chatManager.addLogger(tableDataModel, {name: GlobalData.username, type: MessageType.AUTOTOPUP, money: buyinMoney});
				}

				//玩家赌注小于大盲注时弹出买入界面
				if (tableDataModel.isTournament == false && tableDataModel.gameUIState.isAutoBuyin == false && FloatHandler.TwoFormat(tableDataModel.money) == 0 && tableDataModel.sitChairId > 0)
				{
					var minBuyIn:Number = Math.max(0, tableDataModel.tableDataFromLobby.minBuyAmount - tableDataModel.money);

					var maxBuyIn:Number = Math.max(0, tableDataModel.tableDataFromLobby.maxBuyAmount - tableDataModel.money);

					//弹出购买赌注界面
					dispatcher.dispatchEvent(new MajiangMsgEvent(MajiangEvent.SHOW_CASHIER_VIEW, {tableId: tableDataModel.tableDataFromLobby.tableID, minBuyIn: minBuyIn, maxBuyIn: maxBuyIn}));
				}
			}, 1000);

			//10秒倒计时后清理现场
			var timeoutId:uint = setTimeout(function():void
			{
				clearTimeout(timeoutId);

				logger("比赛结束10后清空桌面");

				//清空手牌
				tableDataModel.tilesInHand = [];
				tableDataModel.playerTiles = [null, [], [], [], [], [], []];
				//清空桌面上的牌
				tableDataModel.tilesOnTable = [];
				tableDataModel.inMatchPlayerList = [];
				tableDataModel.winPlayerList = [];
				tableDataModel.drawPlayerList = [];
				tableDataModel.foldPlayerList = [];
				tableDataModel.losePlayerList = [];

				//清理桌面上剩余牌堆
				tableDataModel.restCardData.restMajiangNum = 0;

				//清空奖池信息
				tableDataModel.bonusPotsData.betPoolNtf = null;

				//比赛结束10后清空桌面
				dispatcher.dispatchEvent(new MajiangEvent(MajiangEvent.CLEAR_TABLE_INFO, tableId.toString()));

				//关闭提示面板
				dispatcher.dispatchEvent(new GameEvent(GameEvent.CLOSE_INFORMATION));

			}, (GlobalData.gameOverClearTime - 2) * 1000);

			logger("比赛结束广播处理时长：" + (getTimer() - startTime));
		}

		/**
		 *下注为零的错误提示
		 * @param pkg
		 *
		 */
		public function OnRecvBetZeroNtf(pkg:MSPKG_BET_ZERO_NTF):void
		{
			logger("不能下零注");
		}

		/**
		 *更改庄家座位ID
		 * @param pkg
		 *
		 */
		public function OnRecvChangeBankerChairIDNtf(pkg:MSPKG_CHANGE_BANKER_CHAIR_ID_NTF):void
		{
			logger("广播更改庄家座位ID" + pkg.bankerChairId);

			var tableId:UInt64 = pkg.tableId;

			//比赛开始前的倒计时
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			tableDataModel.bankerId = pkg.bankerChairId;
		}

		/**
		 *没有足够金钱的错误提示
		 * @param pkg
		 *
		 */
		public function OnRecvNotEnoughMoneyNtf(pkg:MSPKG_NOT_ENOUGH_MONEY_NTF):void
		{
			logger("没有足够金钱的错误提示");
		}

		/**
		 * 获取所在桌子的比赛现场信息
		 * @param pkg
		 */
		public function OnRecvTableLiveInfoNtf(pkg:MSPKG_TABLE_LIVE_INFO_NTF):void
		{
			logger("获取所在桌子的比赛现场信息");
			pkg.liveTableInfos;
		}

		/**
		 * 更新分注池的信息
		 */
		public function OnRecvBetPoolNtf(pkg:MSPKG_BET_POOL_NTF):void
		{
			logger("更新分注池的信息");
			var startTime:int = getTimer();

			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];
			
			if(tableDataModel == null) return;

			tableDataModel.bonusPotsData.betPoolNtf = pkg;

			if (pkg.hasCause)
			{
				switch (pkg.cause)
				{
					case E_BET_POOL_CAUSE.E_BET_POOL_CAUSE_NULL:
					case E_BET_POOL_CAUSE.E_BET_POOL_CAUSE_FOLD:
					case E_BET_POOL_CAUSE.E_BET_POOL_CAUSE_WIN:
						//直接修改奖池信息
						tableDataModel.bonusPotsData.updateView();
						break;
					//底注
					case E_BET_POOL_CAUSE.E_BET_POOL_CAUSE_ANTE:
						var betPool:BET_POOL = pkg.betPool[0];
						//飞底注到奖池
						tableDataModel.chipsToPotEffectData.chipsToPot(betPool.chairList);

						var betPlayers:Array = [];
						//把上轮的押注计算到奖池中
						for (var actionChairId:String in tableDataModel.epicycleBetInfos)
						{
							if (tableDataModel.epicycleBetInfos[actionChairId] != null && tableDataModel.epicycleBetInfos[actionChairId].totalBet > 0)
							{
								tableDataModel.totalBetInGame[int(actionChairId) - 1] = tableDataModel.epicycleBetInfos[actionChairId].totalBet;
							}
						}
						tableDataModel.epicycleBetInfos = [];
						break;
				}
			}
			logger("更新分注池的信息处理时长：" + (getTimer() - startTime));
		}

		/**
		 * 更新玩家的账户余额
		 */
		public function OnRecvBalanceNtf(pkg:MSPKG_BALANCE_NTF):void
		{
			if (pkg.hasTime == false)
			{
				GlobalData.balance = pkg.balance;
			}
			if (pkg.hasTime && pkg.time > GlobalData.updateBalanceTime)
			{
				GlobalData.balance = pkg.balance;
				GlobalData.updateBalanceTime = pkg.time;
			}
		}

		/**
		 * 聊天广播
		 */
		public function OnRecvChatNtf(pkg:MSPKG_CHAT_NTF):void
		{
			/*var tableId:UInt64 = pkg.tableId;
			var name:String = certManager.convertByteArrayToString(pkg.name);
			var info:String = certManager.convertByteArrayToString(pkg.info);

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
			chatManager.addChatMessage(tableDataModel, {name: name, info: info});*/
		}

		/**
		 *修改 是否自动隐藏手牌
		 */
		public function OnRecvAutoHideHandtilesAck(pkg:MSPKG_AUTOHIDE_HANDTILES_ACK):void
		{
			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			tableDataModel.gameUIState.isHideTile = pkg.isAutoHide;
		}

		/**
		 *修改 挂机模式（离开 下盘不参与游戏）
		 */
		public function OnRecvSitoutNtf(pkg:MSPKG_SITOUT_NTF):void
		{
			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			if (tableDataModel.sitChairId == pkg.chairId)
			{
				tableDataModel.gameUIState.isSitOut = pkg.isSitout;
			}
			if (pkg.isSitout == true && tableDataModel.isSitout(pkg.chairId) == false)
			{
				tableDataModel.sitOutPlayerList.push({timer: 1, chairId: pkg.chairId});
			}
			if (pkg.isSitout == false)
			{
				//把玩家从正在比赛的玩家列表中删除
				for (var i:int = 0; i < tableDataModel.sitOutPlayerList.length; i++)
				{
					if (tableDataModel.sitOutPlayerList[i].chairId == pkg.chairId)
					{
						tableDataModel.sitOutPlayerList.splice(i, 1);
						break;
					}
				}
			}

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_SITOUT_NTF.toString(), tableId.toString()));
		}

		/**
		 * 广播某桌子是否可聊天
		 */
		public function OnCanChatNtf(pkg:MSPKG_CANCHAT_NTF):void
		{
			logger("广播某桌子是否可聊天");
			var startTime:int = getTimer();

			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			/*if (tableDataModel.chatUIState.canChat == true && pkg.canChat == false)
			{
				var timeOutId:uint = setTimeout(function():void
				{
					clearTimeout(timeOutId);
					var forbidChatInfo:String = ResourceManager.getInstance().getString("MahjongResource", "forbidChatInfo");
					var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableId).chatMGR;
					chatManager.addLogger(tableDataModel, {name: "", type: MessageType.SYSTEM, message: forbidChatInfo});
				}, 500);
			}
			tableDataModel.chatUIState.canChat = pkg.canChat;*/

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_CANCHAT_NTF.toString(), tableId.toString()));

			logger("广播某桌子是否可聊天处理时长：" + (getTimer() - startTime));
		}

		/**
		 * 询问是否要显示自己的手牌
		 */
		public function OnQueryShowTilesNtf(pkg:MSPKG_QUERY_SHOWTILES_NTF):void
		{
			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			logger("询问是否要显示自己的手牌");

			if (tableDataModel.gameUIState.isHideTile == true)
				return;

			//弹出提示框 让玩家判断是否弃牌
			var data:Object = {};
			data.infoText = ResourceManager.getInstance().getString('MahjongResource', 'showWinTile');
			data.clickYesFunction = function():void
			{
				dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_SHOWTILES_REQ.toString(), {tableId: tableId}));
			};
			dispatcher.dispatchEvent(new GameEvent(GameEvent.SHOW_INFORMATION, data));
		}

		/**
		 * 广播赢家手牌
		 */
		public function OnTilesNtf(pkg:MSPKG_TILES_NTF):void
		{
			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			logger("广播赢家手牌");

			tableDataModel.playerTiles[pkg.chairId] = TileTransform.arrServerToClient(pkg.tiles.sort(TileTransform.sortOnServerTile));

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_TILES_NTF.toString(), pkg));
		}

		/**
		 *锦标赛结束
		 */
		public function OnTnmtFinishedRpt(pkg:MSPKG_TNMT_FINISHED_RPT):void
		{
			logger("锦标赛结束");

			pkg.tnmtId;
		}

		/**
		 *通知玩家他已经被淘汰
		 */
		public function OnTnmtOutMatchRpt(pkg:MSPKG_TNMT_OUTMATCH_RPT):void
		{
			var tnmtId:UInt64 = pkg.tnmtId;
			//获得排名
			var rank:uint = pkg.rank;
			//获得奖金
			var bonus:uint = pkg.bonus;

			var showStr:String = ResourceManager.getInstance().getString('MahjongResource', 'tournamentRanking') + rank;
			if (bonus > 0)
			{
				showStr += "\n" + ResourceManager.getInstance().getString('MahjongResource', 'tournamentWinMoney') + '\n' + FloatHandler.TwoFormatToString(bonus) + '.';
			}

			dispatcher.dispatchEvent(new GameEvent(GameEvent.SHOW_INFO, {info: showStr}));
		}

		/**
		 * 更新锦标赛界面盲注信息
		 */
		public function OnTnmtUpdateBlindAck(pkg:MSPKG_UPDATE_BLIND_ACK):void
		{
			/*logger("更新锦标赛界面盲注信息");
			var startTime:int = getTimer();

			var tournamentId:UInt64 = pkg.tnmtId;
			var blindIndex:uint = pkg.idx; //当前盲注在盲注表中的索引
			var leftsecond:uint = pkg.leftsecond; //剩余秒

			var tournamentDetailModel:TournamentDetailModel = LobbyDataModel.getTournamentDetailById(tournamentId);
			tournamentDetailModel.blindIndex = blindIndex;
			tournamentDetailModel.leftsecond = leftsecond;
			tournamentDetailModel.updateLeftsecondDate = new Date();

			dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_UPDATE_BLIND_ACK.toString()));

			logger("更新锦标赛盲注信息处理时长：" + (getTimer() - startTime));*/
		}

		/**
		 * 接收到拼桌提示
		 */
		public function OnSpliceTableNtf(pkg:MSPKG_SPLICE_TABLE_NTF):void
		{
			logger("接收到拼桌提示");

			UIAllRefer.showStageMask(pkg.tableId);
			var msg:String = ResourceManager.getInstance().getString('MahjongResource', "spliceTableInfo");
			dispatcher.dispatchEvent(new GameEvent(GameEvent.SHOW_WAIT_INFO, msg));
			var timeoutId:uint = setTimeout(function():void
			{
				dispatcher.dispatchEvent(new GameEvent(GameEvent.SHOW_WAIT_INFO));
				clearTimeout(timeoutId);
			}, 3000);
		}

		/**
		 * 锦标赛中更新桌子的大小盲注
		 */
		public function OnUpdateTableBlindNtf(pkg:MSPKG_UPDATE_TABLE_BLIND_NTF):void
		{
			/*logger("锦标赛中更新桌子的大小盲注");

			var tableId:UInt64 = pkg.tableId;
			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[tableId.toString()];

			tableDataModel.tableDataFromLobby.minBlinds = pkg.minBlind;
			tableDataModel.tableDataFromLobby.maxBlinds = pkg.maxBlind;*/

		}

		/**
		 * 踢掉玩家
		 */
		public function OnRecvkickPlayerNtf(pkg:MSPKG_KICK_PLAYER_NTF):void
		{
			logger("踢掉玩家");
			var playername:String = certManager.convertByteArrayToString(pkg.playerName);

		}

		/**
		 * 更新等级经验
		 */
		public function OnRecvVPPNtf(pkg:MSPKG_VPP_NTF):void
		{
			logger("更新等级经验");
			var value:Number = pkg.value;
			GlobalData.myVPP = value;
		}

		/**
		 * 更新牌局编号
		 */
		public function OnRecvMatchIDNtf(pkg:MSPKG_MATCH_ID_NTF):void
		{
			/*(TablesDataManager.tableDataModeDic[pkg.tableId.toString()] as TableDataModel).paijuId = pkg.tableId.toString();
			(TablesDataManager.tableDataModeDic[pkg.tableId.toString()] as TableDataModel).start_time = pkg.startTime;*/
		}

		/** 锦标赛暂停公告 */
		public function OnRecvTournamentRest(pkg:MSPKG_TOURNAMENT_REST_NTF):void
		{
			/*var startTime:Date = new Date();
			startTime.time = pkg.startTime * 1000;

			for each (var tableDataModel:TableDataModel in TablesDataManager.tableDataModeDic)
			{
				//添加系统资讯
				var chatManager:ChatManager = UIAllRefer.instance.getGameUIbyTableId(tableDataModel.tableDataFromLobby.tableID).chatMGR;
				chatManager.addLogger(tableDataModel, {message: "该比赛将暂停，将在" + startTime.toTimeString() + "继续", type: MessageType.SYSTEM});
			}
*/
		}

		public function OnRecvRebuyNtf(pkg:MSPKG_TOURNAMENT_REBUY_NTF):void
		{

			var tableDataModel:TableDataModel = TablesDataManager.tableDataModeDic[pkg.tableId.toString()];

			if (tableDataModel._sitChairId == pkg.chairId)
			{
				var data:Object = {};
				data.infoText = "是否花费" + pkg.rebuyFee + "买入筹码继续锦标赛";
				data.clickYesFunction = function():void
				{
					dispatcher.dispatchEvent(new MajiangMsgEvent(MSProto.MSID_TOPUP_REQ.toString(), {tableId: pkg.tableId, money: 0}));
				};
				//弹出确认界面
				dispatcher.dispatchEvent(new GameEvent(GameEvent.SHOW_INFORMATION, data));

				setTimeout(function():void
				{
					dispatcher.dispatchEvent(new GameEvent(GameEvent.CLOSE_INFORMATION));
				}, 30000);
			}


		}

	}
}
